home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
hard
/
drivr
/
BetaScan_1.12.lha
/
BetaScan
/
ScannerDev
/
MakeILBM.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-10-04
|
12KB
|
451 lines
/************************************************************************/
/* */
/* Write image as ilbm */
/* */
/* */
/* */
/* */
/************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <exec/types.h>
#include <datatypes/pictureclass.h>
#include "MakeILBM.h"
#include "packer.h"
#define ID_XBMI MAKE_ID('X','B','M','I')
#define ILBM_BUFLEN 1500000
struct ImageBuf
{
UBYTE* buf;
ULONG actualLen;
FILE* fh;
};
struct ILBMFile
{
char* fileName;
int formLenOffset;
int bodyLenOffset;
UBYTE flags;
UBYTE depth;
UWORD width;
UWORD height;
UWORD xdpi;
UWORD ydpi;
ULONG scanLineWidth;
ULONG bufLen;
struct ImageBuf buf[3];
};
#define ILBMFLAGS_COMPRESS (0x01 << 0)
#define ILBMFLAGS_TEMPFILE (0x01 << 1)
struct xbmi
{
WORD xbmi_type; /* ILBM_PAL, ILBM_RGB, ... (se below) */
WORD xbmi_xdpi;
WORD xbmi_ydpi;
};
#define ILBM_PAL 0 /* BODY data = indexes into the palette (CMAP)
* numcolors = 1<<depth;
*/
#define ILBM_GREY 1 /* BODY = grayscale values
* Bits per sample = number of bitplanes.
* Samples per pixel = 1.
* black = 0, white = (1<<depth)-1;
*/
#define ILBM_RGB 2 /* BODY data = red, green, and blue values.
* Bits per sample = depth/3.
* Samples per pixel = 3.
*/
#define ILBM_RGBA 3 /* BODY data = red, green, blue, and alpha
* channel values.
* Bits per sample = depth/4.
* Samples per pixel = 4.
*/
#define ILBM_CMYK 4 /* BODY data = cyan, magenta, yellow, and black
* values.
* Bits per sample = depth/4.
* Samples per pixel = 4.
*/
#define ILBM_CMYKA 5 /* BODY data = cyan, magenta, yellow, black,
* and alpha channel values.
* Bits per sample = depth/5.
* Samples per pixel = 5.
*/
#define ILBM_BW 6 /* BODY data = black and white bits.
* Bits per sample = 1.
* Samples per pixel = 1.
* white = 0, black = 1.
*/
static char* tempfile[3] = {"temp.red","temp.green","temp.blue"};
static void makePlane(UBYTE* source,UBYTE* dest,int bit,int length)
{
int bitNum,byteNum;
UBYTE b,sourceMask;
sourceMask = 0x01 << bit;
for( byteNum = 0 ; byteNum < length ; byteNum++ )
{
UBYTE destMask;
destMask = 0x80;
b = 0;
for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
{
if( (*source) & sourceMask )
b |= destMask;
destMask >>= 1;
source++;
}
*(dest++) = b;
}
}
static void makeILBM(struct ILBMFile* ilbmfh)
{
struct BitMapHeader BMHD;
struct xbmi XBMI;
FILE* fh;
int c;
if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
{
for( c = 0 ; c < 3 ; c++ )
{
ilbmfh->buf[c].fh = fopen(tempfile[c],"r");
setvbuf(ilbmfh->buf[c].fh,ilbmfh->buf[c].buf,_IOFBF,ilbmfh->bufLen);
}
}
BMHD.bmh_Width = ilbmfh->width;
BMHD.bmh_Height = ilbmfh->height;
BMHD.bmh_Left = 0;
BMHD.bmh_Top = 0;
BMHD.bmh_Depth = ilbmfh->depth;
BMHD.bmh_Masking = 0;
BMHD.bmh_Pad = 0;
BMHD.bmh_Transparent = 0;
BMHD.bmh_XAspect = 1;
BMHD.bmh_YAspect = 1;
BMHD.bmh_PageWidth = ilbmfh->width;
BMHD.bmh_PageHeight = ilbmfh->height;
switch( ilbmfh->depth )
{
case 1:
XBMI.xbmi_type = ILBM_BW;
break;
case 8:
XBMI.xbmi_type = ILBM_GREY;
break;
case 24:
XBMI.xbmi_type = ILBM_RGB;
break;
}
XBMI.xbmi_xdpi = ilbmfh->xdpi;
XBMI.xbmi_ydpi = ilbmfh->ydpi;
if( fh = fopen(ilbmfh->fileName,"w") )
{
int scanLine,color,bitNum;
ULONG lineLen,bodyLen,formLen;
ULONG temp,psize;
UBYTE *line;
UBYTE *pline = NULL;
UBYTE *scanbuf = NULL;
lineLen = ((ilbmfh->width+7)/8+1) & 0xFFFFFFFE;
line = malloc(lineLen);
if( (ilbmfh->flags & ILBMFLAGS_COMPRESS) && (pline = malloc(lineLen*2)) )
BMHD.bmh_Compression = 1;
else
BMHD.bmh_Compression = 0;
temp = ID_FORM;
fwrite(&temp,4,1,fh);
ilbmfh->formLenOffset = ftell(fh);
temp = 0;
fwrite(&temp,4,1,fh);
temp = ID_ILBM;
fwrite(&temp,4,1,fh);
temp = ID_BMHD;
fwrite(&temp,4,1,fh);
temp = sizeof(struct BitMapHeader);
fwrite(&temp,4,1,fh);
fwrite(&BMHD,sizeof(struct BitMapHeader),1,fh);
temp = ID_XBMI;
fwrite(&temp,4,1,fh);
temp = sizeof(struct xbmi);
fwrite(&temp,4,1,fh);
fwrite(&XBMI,sizeof(struct xbmi),1,fh);
if( ilbmfh->depth == 1 )
{
UBYTE b;
temp = ID_CMAP;
fwrite(&temp,4,1,fh);
temp = 3*2;;
fwrite(&temp,4,1,fh);
b = 0xFF;
fwrite(&b,1,1,fh);
fwrite(&b,1,1,fh);
fwrite(&b,1,1,fh);
b = 0;
fwrite(&b,1,1,fh);
fwrite(&b,1,1,fh);
fwrite(&b,1,1,fh);
}
else if( ilbmfh->depth == 8 )
{
UBYTE b;
int i;
temp = ID_CMAP;
fwrite(&temp,4,1,fh);
temp = 3*256;;
fwrite(&temp,4,1,fh);
for( i = 0 ; i < 256 ; i++ )
{
b = (UBYTE)i;
fwrite(&b,1,1,fh);
fwrite(&b,1,1,fh);
fwrite(&b,1,1,fh);
}
}
temp = ID_BODY;
fwrite(&temp,4,1,fh);
ilbmfh->bodyLenOffset = ftell(fh);
temp = 0;
fwrite(&temp,4,1,fh);
if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
scanbuf = malloc(ilbmfh->scanLineWidth);
switch( ilbmfh->depth )
{
case 1:
for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
{
if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
else
scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
if( pline == NULL )
fwrite(scanbuf,lineLen,1,fh);
else
{
psize = PackRow(scanbuf,pline,lineLen);
fwrite(pline,psize,1,fh);
}
}
break;
case 8:
for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
{
if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
else
scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
{
makePlane(scanbuf,line,bitNum,lineLen);
if( pline == NULL )
fwrite(line,lineLen,1,fh);
else
{
psize = PackRow(line,pline,lineLen);
fwrite(pline,psize,1,fh);
}
}
}
break;
case 24:
for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
{
for( color = 0 ; color < 3 ; color++ )
{
if( ilbmfh->buf[color].buf )
{
if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[color].fh);
else
scanbuf = ilbmfh->buf[color].buf + scanLine*ilbmfh->scanLineWid